﻿using System;
using System.Drawing;

namespace TodoSoft.Controls
{
	public class Graphics : IDisposable
	{
		public Point Translate = new Point(0, 0);

		private readonly Brush _textBackColorBrush;
		private readonly System.Drawing.Graphics _graphics;
		private readonly bool _disposeInnerGraphics;

		public Graphics(System.Drawing.Graphics graphics, bool disposeInnerGraphics)
		{
			_graphics = graphics;
			_disposeInnerGraphics = disposeInnerGraphics;
			_textBackColorBrush = new SolidBrush(Color.White);
		}

		public static Graphics FromImage(Image image)
		{
			var graphics = System.Drawing.Graphics.FromImage(image);
			return new Graphics(graphics, true);
		}

		public void Dispose()
		{
			if(_disposeInnerGraphics)
				_graphics.Dispose();

			_textBackColorBrush.Dispose();
		}

		public void FillRectangle(SolidBrush backColorSolidBrush, Rectangle clipRectangle)
		{
			clipRectangle.X += Translate.X;
			clipRectangle.Y += Translate.Y;
			_graphics.FillRectangle(backColorSolidBrush, clipRectangle);
		}

		public void DrawImage(Bitmap cachedBitmap, int x, int y)
		{
			_graphics.DrawImage(cachedBitmap, x + Translate.X, y + Translate.Y);
		}

		public void DrawLine(Pen borderPen, int x1, int y1, int x2, int y2)
		{
			_graphics.DrawLine(borderPen, x1+Translate.X, y1+Translate.Y, x2+Translate.X, y2+Translate.Y);
		}

		public void DrawString(string text, Font font, Brush brush, Rectangle rect)
		{
			DrawString(text, font, brush, rect, new StringFormat());
		}

		public SizeF MeasureString(string text, Font font)
		{
			return _graphics.MeasureString(text, font);
		}

		internal void DrawString(
			string text, 
			Font font, 
			Brush brush, 
			Rectangle rect, 
			StringFormat stringFormat)
		{
			// To avoid aliasing issues it is necessary draw text into image without clipping.
			using (var bitmap = new Bitmap(rect.Width, rect.Height))
			using (var g = System.Drawing.Graphics.FromImage(bitmap))
			{
				g.FillRectangle(_textBackColorBrush, new Rectangle(0, 0, rect.Width, rect.Height));

				g.DrawString(
						text,
						font,
						brush,
						new Rectangle(0, 0, bitmap.Width, bitmap.Height),
						stringFormat);
			
				rect.X += Translate.X;
				rect.Y += Translate.Y;

				_graphics.DrawImage(bitmap, rect.X, rect.Y);
			}
		}
	}
}